package com.mask.common.file.service;

import com.mask.common.file.config.FileProperties;
import com.mask.common.file.service.FileService;
import com.mask.common.file.utils.FileUtils;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Slf4j
@Service
@ConditionalOnProperty(prefix = "mask.file", name = "storage-type", havingValue = "MINIO")
public class MinioFileService implements FileService {
    @Autowired
    private MinioClient minioClient;
    
    @Autowired
    private FileProperties properties;

    @PostConstruct
    public void init() throws Exception {
        boolean exists = minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(properties.getMinio().getBucketName())
                .build());
        if (!exists) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(properties.getMinio().getBucketName())
                    .build());
        }
    }

    @Override
    public String upload(MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String extension = FileUtils.getExtension(originalFilename);
        String fileName = UUID.randomUUID().toString() + extension;
        
        String dateDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        String objectName = dateDir + "/" + fileName;
        
        try {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(properties.getMinio().getBucketName())
                    .object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
                    
            return properties.getMinio().getEndpoint() + "/" + 
                   properties.getMinio().getBucketName() + "/" + objectName;
        } catch (Exception e) {
            log.error("上传文件到MinIO失败", e);
            throw new IOException("上传文件失败", e);
        }
    }

    @Override
    public void delete(String filePath) {
        try {
            String objectName = filePath.substring(filePath.indexOf(
                              properties.getMinio().getBucketName()) + 
                              properties.getMinio().getBucketName().length() + 1);
                              
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(properties.getMinio().getBucketName())
                    .object(objectName)
                    .build());
        } catch (Exception e) {
            log.error("从MinIO删除文件失败", e);
        }
    }

    @Override
    public void download(String filePath, HttpServletResponse response) throws IOException {
        try {
            String objectName = filePath.substring(filePath.indexOf(
                              properties.getMinio().getBucketName()) + 
                              properties.getMinio().getBucketName().length() + 1);
                              
            GetObjectResponse object = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(properties.getMinio().getBucketName())
                    .object(objectName)
                    .build());
                    
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=" + 
                             URLEncoder.encode(FileUtils.getName(objectName), "UTF-8"));
            
            IOUtils.copy(object, response.getOutputStream());
            object.close();
        } catch (Exception e) {
            log.error("从MinIO下载文件失败", e);
            throw new IOException("下载文件失败", e);
        }
    }
}